/**
 * Created by Yu Jin Xian on 2016/9/14.
 */
function unaryOperators() {
    function incrementWithDecrement() {
        function incrementBefore() {
            var age = 29;
            ++age;

            function equals() {
                var age = 29;
                age = age + 1;
            }
        }

        function decrementBefore() {
            var age = 29;
            --age;

            function equals() {
                var age = 29;
                age = age - 1;
            }
        }

        function eval() {
            var age = 29;
            var anotherAge = --age + 2;
            alert(age);                     // 输出 28
            alert(anotherAge);              // 输出 30
        }

        function eval1() {
            var num1 = 2;
            var num2 = 20;
            var num3 = --num1 + num2;       // 等于 21
            var num4 = num1 + num2;         // 等于 21
        }

        function incrementAfter() {
            var age = 29;
            age++;

            var num1 = 2;
            var num2 = 20;
            var num3 = num1-- + num2;       // 等于 22
            var num4 = num1 + num2;         // 等于 21
        }

        function decrememtAfter() {
            var age = 29;
            age--;
        }

        function eval2() {
            var s1 = '2';
            var s2 = 'z';
            var b = false;
            var f = 1.1;
            var o = {
                valueOf: function () {
                    return -1;
                }
            };

            s1++;                           // 值变成数值 3
            s2++;                           // 值变成 NaN
            b++;                            // 值变成数值 1
            f--;                            // 值变成 0.100000000000000009 (由于浮点舍入错误所致)
            o--;                            // 值变成 -2
        }
    }

    function unaryAdditionWithSubtraction() {
        var num = 25;
        num = +num;                         // 仍然是 25

        function eval() {
            var s1 = '01';
            var s2 = '1.1';
            var s3 = 'z';
            var b = false;
            var f = 1.1;
            var o = {
                valueOf: function () {
                    return -1;
                }
            };

            s1 = +s1;                       // 值变成数值 1
            s2 = +s2;                       // 值变成数值 1.1
            s3 = +s3;                       // 值变成 NaN
            b = +b;                         // 值变成数值 0
            f = +f;                         // 值变成数值 1.1
            o = +o;                         // 值变成数值 -1
        }

        function eval1() {
            var s1 = '01';
            var s2 = '1.1';
            var s3 = 'z';
            var b = false;
            var f = 1.1;
            var o = {
                valueOf: function () {
                    return -1;
                }
            };

            s1 = -s1;                       // 值变成数值 -1
            s2 = -s2;                       // 值变成数值 -1.1
            s3 = -s3;                       // 值变成 NaN
            b = -b;                         // 值变成数值 0
            f = -f;                         // 值变成数值 -1.1
            o = -o;                         // 值变成数值 1
        }
    }
}

function binaryOpertors() {
    // 二进制补码
    // 0000 0000 0000 0000 0000 0000 0001 0010
    // 1111 1111 1111 1111 1111 1111 1110 1101
    //                                       1
    // 1111 1111 1111 1111 1111 1111 1110 1110
    var num = -18;
    alert(num.toString(2));         // "-10010"

    function not() {
        var num1 = 25;              // 二进制 0000 0000 0000 0000 0000 0001 1001
        var num2 = ~num1;           // 二进制 1111 1111 1111 1111 1111 1110 0110
        alert(num2);                // -26

        function eval1() {
            var num1 = 25;
            var num2 = -num1 - 1;
            alert(num2);            // "-26"
        }
    }

    function and() {
        var result = 25 & 3;
        alert(result);              // 1
        //  25 = 0000 0000 0000 0000 0000 0000 0001 1001
        //   3 = 0000 0000 0000 0000 0000 0000 0000 0011
        // ---------------------------------------------
        // AND = 0000 0000 0000 0000 0000 0000 0000 0001
    }

    function or() {
        var result = 25 | 3;
        alert(result);              // 27
        //  25 = 0000 0000 0000 0000 0000 0000 0001 1001
        //   3 = 0000 0000 0000 0000 0000 0000 0000 0011
        // ---------------------------------------------
        //  OR = 0000 0000 0000 0000 0000 0000 0001 1011
    }

    function xor() {
        var result = 25 ^ 3;
        alert(result);              // 26
        //  25 = 0000 0000 0000 0000 0000 0000 0001 1001
        //   3 = 0000 0000 0000 0000 0000 0000 0000 0011
        // ---------------------------------------------
        // XOR = 0000 0000 0000 0000 0000 0000 0001 1010
    }

    function leftShift() {
        var oldValue = 2;               // 等于二进制的 10
        var newValue = oldValue << 5;   // 等于二进制的 1000000, 十进制的 64
    }

    function urightShift() {
        var oldValue = 64;              // 等于二进制的 1000000
        var newValue = oldValue >> 5;   // 等于二进制的 10, 即十进制的 2
    }

    function rightShift() {
        var oldValue = 2;               // 等于二进制的 10
        var newValue = oldValue >>> 5;  //  等于二进制的 10, 即十进制的 2

        function negative() {
            var oldValue = -64;             // 等于二进制的 1111 1111 1111 1111 1111 1111 1100 0000
            var newValue = oldValue >>> 5;  // 等于十进制的 134217726
        }
    }
}

function booleanOpertors() {
    function not() {
        alert(!false);              // true;
        alert(!'blue');             // false;
        alert(!0);                  // true;
        alert(!NaN);                // true;
        alert(!'');                 // true;
        alert(!12345);              // false;

        alert(!!false);             // false;
        alert(!!'blue');            // true;
        alert(!!0);                 // false;
        alert(!!NaN);               // false;
        alert(!!'');                // false;
        alert(!!12345);             // true;
    }

    function and() {
        var result = true && false;

        function error() {
            var found = true;
            var result = (found && someUndefinedVariable);  // 这里会发生错误
            alert(result);                                  // 这一行不会执行
        }

        function noerror() {
            var found = false;
            var result = (found && someUndefinedVariable);  // 不会发生错误
            alert(result);                                  // 会执行 ("false")
        }
    }

    function or() {
        var result = true || false;

        function noerror() {
            var found = true;
            var result = (found || someUndefinedVariable);  // 不会发生错误
            alert(result);                                  // 会执行 ("true")
        }

        function error() {
            var found = false;
            var result = (found || someUndefinedVariable);  // 这里会发生错误
            alert(result);                                  // 这一行不会执行
        }

        var backupObject = {};
        var myObject = preferredObject || backupObject;
    }
}

function multiplyWithDivideOpertors() {
    function multiply() {
        var result = 34 * 56;
    }

    function divide() {
        var result = 66 / 11;
    }

    function mod() {
        var result = 26 % 5;
    }
}

function addWithSubtractOpertors() {
    function addition() {
        var result = 1 + 2;

        var result1 = 5 + 5;        // 两个数值相加
        alert(result1);             // "10"
        var result2 = 5 + '5';      // 一个数值和一个字符串相加
        alert(result2);             // "55"

        function concat() {
            var num1 = 5;
            var num2 = 10;
            var message = 'The sum of 5 and 10 is ' + num1 + num2;
            alert(message);         // "The sum of 5 and 10 is 510"
        }

        function priority() {
            var num1 = 5;
            var num2 = 10;
            var message = 'The sum of 5 and 10 is ' + (num1 + num2);
            alert(message);
        }
    }

    function subtraction() {
        var result = 2 - 1;

        function eval() {
            var result1 = 5 - true; // 4, 因为 true 被转换成了 1
            var result2 = NaN - 1;  // NaN
            var result3 = 5 - 3;    // 2
            var result4 = 5 - '';   // 5, 因为 "" 被转换成了 0
            var result5 = 5 - '2';  // 3, 因为 "2" 被转换成了 2
            var result6 = 5 - null; // 5, 因为 null 被转换成了 0
        }
    }
}

function relationalOperators() {
    function greaterThanLessThan() {
        var result1 = 5 > 3;                    // true
        var result2 = 5 < 3;                    // false

        function compareEncoding() {
            var result = 'Brick' < 'alphabet';  // true
        }

        function compareEncoding1() {
            var result = 'Brick'.toLowerCase() < 'alphabet';    // false
        }

        function compareEncoding2() {
            var result = '23' < '3';            // true
        }

        function compareEncoding3() {
            var result = '23' < 3;              // false
        }

        function compareEncoding4() {
            var result = 'a' < 3;               // false, 因为 "a" 被换转成了 NaN
        }

        function compareEncoding5() {
            var result1 = NaN < 3;              // false
            var result2 = NaN >= 3;             // false
        }
    }
}

function equalsOperators() {
    var result1 = null == undefined;    // true
    var result2 = 'NaN' == NaN;         // false
    var result3 = 5 == NaN;             // false
    var result4 = NaN == NaN;           // false
    var result5 = NaN != NaN;           // true
    var result6 = false == 0;           // true
    var result7 = true == 1;            // true
    var result8 = true == 2;            // false
    var result9 = undefined == 0;       // false
    var result10 = null == 0;           // false
    var result11 = '5' == 5;            // true

    function CongruentOperator() {
        var result1 = '55' == 55;       // true, 因为转换后相等
        var result2 = '55' === 55;      // false, 因类不同的数据类型不相等

        var result3 = '55' != 55;       // false, 因为转换后相等
        var result4 = '55' !== 55;      // true, 因类不同的数据类型不相等

        var result5 = null == undefined;    // true
        var result6 = null === undefined;   // false
    }
}

function ternaryOperations() {
    var num1 = 3, num2 = 2;
    var max = (num1 > num2) ? num1 : num2;
}

function assignmentOperators() {
    var num = 10;

    function compoundAssignment() {
        var num = 10;
        num = num + 10;

        function or() {
            var num = 10;
            num += 10;
        }
    }
}

function commaOperators() {
    var num = 1, num2 = 2, num3 = 3;

    function multiAssignment() {
        var num = (5, 1, 4, 8, 0);  // num 的值为 0
    }
}